#include "Gun.h"
#include "easylogging++.h"
#include <Windows.h>
#include "Global.h"
#include <cmath>

Gun::Gun()
{

}

Gun::Gun(std::string name, double magnification, int step, int interval, std::vector<int> offsetVector, GunAttachment muzzle, GunAttachment grip, GunAttachment sight, GunAttachment butt)
{
	this->name = name;
	this->magnification = magnification;
	this->step = step;
	this->interval = interval;
	size_t loopCount = 40 - offsetVector.size();
	int lastMove = offsetVector[offsetVector.size() - 1];
	for (size_t i = 0; i < loopCount; i++)
	{
		offsetVector.push_back(lastMove);
	}
	this->offsetVector = offsetVector;
	this->muzzle = muzzle;
	this->grip = grip;
	this->sight = sight;
	this->butt = butt;
}
Gun::~Gun()
{
}

void Gun::computeMovements()
{
	std::vector<int> offsetVectorItem;
	LOG(DEBUG) << name << " computeMovements";
	if ((GetKeyState(VK_CAPITAL) & 0x0001) != 0)
	{
		LOG(DEBUG) << "full_configuration";
		for (int i = 0; i < offsetVector.size(); i++)
		{
			double result = std::round(offsetVector[i] * global_constant.full_magnification * this->magnification);
			if (global_constant.posture == 1)
			{
				result = std::round(result * global_constant.squat_magnification);
			}
			else
			{
				result = std::round(result * global_constant.stand_magnification);
			}
			offsetVectorItem.push_back(result);
		}
	}
	else
	{
		LOG(DEBUG) << "low_configuration";
		for (int i = 0; i < offsetVector.size(); i++)
		{
			double result = std::round(offsetVector[i] * global_constant.low_magnification * this->magnification);
			if (global_constant.posture == 1)
			{
				result = std::round(result * global_constant.squat_magnification);
			}
			else
			{
				result = std::round(result * global_constant.stand_magnification);
			}
			offsetVectorItem.push_back(result);
		}
	}

	std::ostringstream oss;
	for (const auto& offset : offsetVectorItem) {
		oss << offset << " ";
	}
	LOG(DEBUG) << "offsetVectorItem: " << oss.str();

	int interval_quotient = interval / step;
	int interval_remainder = interval % step;

	// 实战模式位移数据
	std::vector<int> offsetVectorLong;
	for (int i = 0; i < 40; i++)
	{
		if (i <= offsetVectorItem.size() - 1)
		{
			offsetVectorLong.push_back(offsetVectorItem[i]);
		}
		else
		{
			offsetVectorLong.push_back(offsetVectorItem[offsetVectorItem.size() - 1]);
		}
	}
	movementsLong.clear();
	for (int i = 0; i < offsetVectorLong.size(); i++)
	{
		int move_quotient = offsetVectorLong[i] / step;
		int move_remainder = offsetVectorLong[i] % step;
		std::vector<MovementParams> movementsItem;
		for (int j = 0; j < step && move_quotient != 0; j++)
		{
			MovementParams movement_params;
			movement_params.interval = interval_quotient;
			movement_params.distance = move_quotient;
			movementsItem.push_back(movement_params);
		}
		if (move_remainder != 0 || interval_remainder != 0)
		{
			MovementParams movement_params;
			movement_params.interval = interval_remainder;
			movement_params.distance = move_remainder;
			movementsItem.push_back(movement_params);
		}
		movementsLong.push_back(movementsItem);
	}

	// 调试模式位移数据
	movements.clear();
	for (int i = 0; i < offsetVectorItem.size(); i++)
	{
		int move_quotient = offsetVectorItem[i] / step;
		int move_remainder = offsetVectorItem[i] % step;
		std::vector<MovementParams> movementsItem;
		for (int j = 0; j < step && move_quotient != 0; j++)
		{
			MovementParams movement_params;
			movement_params.interval = interval_quotient;
			movement_params.distance = move_quotient;
			movementsItem.push_back(movement_params);
		}
		if (move_remainder != 0 || interval_remainder != 0)
		{
			MovementParams movement_params;
			movement_params.interval = interval_remainder;
			movement_params.distance = move_remainder;
			movementsItem.push_back(movement_params);
		}
		movements.push_back(movementsItem);
	}
}

bool Gun::gunIsSafe()
{
	if (step == 0)
	{
		return false;
	}
	if (interval == 0)
	{
		return false;
	}
	return true;
}

double Gun::computeRecoil()
{
	double recoil = 1;
	if (muzzle.recoilCoefficient != 1)
	{
		recoil *= muzzle.recoilCoefficient;
	}
	if (grip.recoilCoefficient != 1)
	{
		recoil *= grip.recoilCoefficient;
	}
	if (sight.recoilCoefficient != 1)
	{
		recoil *= sight.recoilCoefficient;
	}
	if (butt.recoilCoefficient != 1)
	{
		recoil *= butt.recoilCoefficient;
	}
	return recoil;
}

void Gun::printInfo()
{
	LOG(DEBUG) << "Gun Name: " << name;
	LOG(DEBUG) << "Step: " << step;
	LOG(DEBUG) << "Interval: " << interval;
	std::ostringstream oss;
	for (const auto& offset : offsetVector) {
		oss << offset << " ";
	}
	LOG(DEBUG) << "Offset Vector: " << oss.str();
	LOG(DEBUG) << "Muzzle: " << muzzle.recoilCoefficient;
	LOG(DEBUG) << "Grip: " << grip.recoilCoefficient;
	LOG(DEBUG) << "Sight: " << sight.recoilCoefficient;
	LOG(DEBUG) << "Butt: " << butt.recoilCoefficient;
}
